package com.rparoxysm.tribase.data.types;

import com.rparoxysm.util.Debug;

import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.GregorianCalendar;

public class WeatherConditionKey {
    static Debug debug = new Debug("WeatherConditionKey");

    public WeatherConditionKey(Calendar when, String where) {
	
	dtg = new GregorianCalendar();
	dtg.setTime(when.getTime());
	dtg.clear(Calendar.MINUTE);
	dtg.clear(Calendar.SECOND);
	dtg.set(Calendar.MILLISECOND, hashStation(where));
	
	debug.print(debug.INFO, "Key value for '" + 
		    WeatherCondition.formatDate(when) + "' at '" + 
		    where + "' is: " + hashCode());
    }
    
    public int hashCode() {
	return (int) (dtg.getTimeInMillis() % Integer.MAX_VALUE);
    }
    
    public boolean equals(WeatherConditionKey other) {
	return (other != null) && 
	    (this.dtg.getTimeInMillis() == other.dtg.getTimeInMillis());
    }
    
    public String toString() {
	String time = WeatherCondition.formatDate(dtg);

	byte[] station = new byte[stationLength];
	int stationCode = 
	    dtg.get(Calendar.MINUTE) * 60000 + 
	    dtg.get(Calendar.SECOND) * 1000 +
	    dtg.get(Calendar.MILLISECOND);
	
	debug.print(Debug.INFO, "Station code: " + stationCode);

	for(int i = 0; i < stationLength; ++i) {
	    debug.print(Debug.INFO, "Station code = " + stationCode +
			" stationCode / 26 = " + stationCode / 26 +
			" stationCode % 26 = " + stationCode % 26);

	    station[i] = (byte) ((stationCode % 26) + 'A');
	    stationCode /= 26;
	}

	return time + " at " + new String(station);
    }
    
    private static final int pow26[] = {1, 26, 676, 17576};
    private int hashStation(String station) {
	int code = 0;
	stationLength = 0;
	byte[] stationChars;
	if(station != null) {
	    try {
		stationChars = station.getBytes("US-ASCII");
		stationLength = stationChars.length;
		for(int i = stationLength - 1; i >= 0; --i) {
		    debug.print(Debug.INFO, i + ": Hashing '" + 
				(char) stationChars[i] +
				"'(" + charToNumber(stationChars[i]) + ")" +
				" * 26^" + i + "(" + pow26[i] + ") + " + code);

		    code += charToNumber(stationChars[i]) * pow26[i];
		}
	    } catch (UnsupportedEncodingException e) {
		debug.print(Debug.ERROR, e.getMessage());
	    }
	} else {
	    debug.print(Debug.ERROR, "No station found in WeatherCondition");
	}
	
	if(code >= (60 * 60 * 1000)) {
	    debug.print(Debug.ERROR, "Station hash (" + code + ") for '" +
			station + "' too large");
	}
	    
	return code;
    }
    
    private int charToNumber(byte ch) {
	
	if('A' <= ch && ch <= 'Z')      ch -= 'A';
	else if('a' <= ch && ch <= 'z') ch -= 'a';
	else                            ch = 0;
	
	return ch;
    }
    
    private Calendar dtg;
    private int stationLength;
}
